﻿using System;
using System.Collections.Generic;

namespace N2.Workflow
{
	using Items;
	
	public interface IWorkflowProvider
	{
		/// <summary>
		/// Tries to resolve a workflow state information associated with a given item
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		IItemState GetCurrentState(ContentItem item);
		
		/// <summary>
		/// Similar to the GetCurrentState, but under type constraint
		/// </summary>
		/// <typeparam name="StateType"></typeparam>
		/// <param name="item"></param>
		/// <returns></returns>
		StateType GetLatestState<StateType>(ContentItem item) where StateType : IItemState;

		IItemState GetLatestState(ContentItem item, Type stateType);

		/// <summary>
		/// A history of workflow states for a given item
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		IEnumerable<IItemState> GetHistory(ContentItem item);
		
		/// <summary>
		/// A workflow definition, that drives this item
		/// </summary>
		/// <param name="item"></param>
		/// <returns></returns>
		IWorkflowDefinition GetDefinition(ContentItem item);
		
		/// <summary>
		/// Execute a workflow action over item by supplying it's name
		/// and a bag of properties to initialize new item state
		/// </summary>
		/// <param name="item">the item to change state for</param>
		/// <param name="actionName">name of the action to execute, should be among valid actions for a current item state</param>
		/// <param name="values">an object which public properties, used to initialise a new item state</param>
		/// <returns>newly assigned state</returns>
		IItemState PerformAction(ContentItem item, string actionName, object values);
//TODO make internal ?
		IItemState PerformAction(ContentItem item, IItemState newState);
		
		/// <summary>
		/// Returns a workflow action definition by it's name.
		/// The action should be among a valid actions for a 
		/// current workflow state, in which a given item resides.
		/// </summary>
		/// <param name="item">Item to resolve an action for</param>
		/// <param name="actionName">Name property of a workflow action definition</param>
		/// <returns></returns>
		IActionDefinition ResolveActionForItem(ContentItem item, string actionName);
	}
}
